查看原文
其他

Android面试看完这篇文章就可以了

专注于编程、互联网动态。最终将总结的技术、心得、经验(数据结构与算法、源码分析等)分享给大家,这里不止限于技术!还有职场心得、生活感悟、以及面经点击上方 "程序员小乐" ,关注公众号,第一时间送达!

每日英文 

Smile and stop complaining about the things you can't change. Time keeps ticking whether you're happy or sad.

保持微笑,停止抱怨那些改变不了的事。无论你开心与否,时间总是不等人的。


小乐有话说 

现实会告诉你,不努力就会被生活给踩死,无需找什么借口,一无所有,就是拼的理由。


来自:fengcz

链接:https://www.jianshu.com/p/8e7dc57c4547

封面来自网络


01 Java基础篇



  • java基本数据类型及所占字节数

8种基本数据类型

总结:byte=boolean(1)<char=short(2)<int =float(4)<long=double(8)
每个类型所占bit数=字节*8(bit) 1byte=8bit

  • java的特性

    封装、继承、多态(三大特性)、抽象

  • 什么是多态

    多态机制是依靠继承机制实现的

  • 理解面向对象编程思想

  • static可修饰什么?有什么作用?

    static可修饰方法、变量、类、代码块:被static修饰的变量和方法是独立于该类的,它不依赖于某个特定的实例变量,也就是说它被该类的所有实例共享。

    静态变量:在类加载时被完成初始化,它在内存中仅有一个,且JVM也只会为它分配一次内存
    静态方法:在类加载的时候就存在了,它不依赖于任何实例,所以static方法必须实现,也就是说他不能是抽象方法abstract。

    static修饰类时,只可修饰内部类。

    被static修饰的代码块,我们称之为静态代码块,静态代码块会随着类的加载一块执行,而且他可以随意放,可以存在于该了的任何地方。

    静态的就是共享的

    静态方法中不可调用非静态方法

  • final可修饰什么?有什么作用?

    final可修饰类、方法、变量
    被final修饰的类不能被继承
    被final修饰的方法不可被重写,可以被重载(也必须是final方法)
    被final修饰的变量载声明的时候必须进行初始化,之后不可被修改

  • 方法的重载、重写

    重载:overload->同一个类中有多个同名的方法(参数个数或参数类型或参数顺序不一样);好处是提高效率,省时省力;

    重写:override->重写通常是重写父类方法,当父类方法不能满足业务需求时,可以对父类中的方法进行重写

  • sleep与wait的区别?

    wait是Object的一个函数,指线程处于进入等待状态,此时线程不占用任何资源,不增加时间限制。wait可以被notify和notifyAll函数唤醒(这两个也是Object的函数)。

    sleep则是Thread的一个函数,指线程被调用时,占着CPU不工作.此时,系统的CPU部分资源被占用,其他线程无法进入,会增加时间限制。

区别:

1、sleep()不会释放同步资源对象锁,wait()会释放对象锁
2、sleep()可以在任何地方使用,wait()只能在同步方法或代码块使用(synchronized)
3、sleep()是Thread类中的方法(调用时会暂停此线程指定的时间,监控依旧,不会释放对象锁,到时自动恢复),wait()是Object类中的方法(调用会放弃对象锁,进入等待队列,待调用notify()/notifyAll()唤醒指定的线程或者所有线程,才会进入锁池,
不再次获得对象锁才会进入运行状态)

  • equals与==的区别?

1、equals 是方法,而 == 是操作符(基本数据类型比较只能用==来判断)
2、equals()方法是用来判断其他的对象是否和该对象相等(equals方法没有被重写时比较的是它们在内存中的存放地址,若重写了则按自定义的规则来判断)

线程

  • 创建线程的方式

1、通过继承Thead类并重写写run()函数的方式
2、通过实现Runnable接口的方法

方式1:
public class CreateThreadOne extends Thread {
        @Override
        public void run() {
            super.run();
        }
    }
方式2:
public class CreateThreadTwo implements Runnable {

        @Override
        public void run() {

        }
    }
用法:
new CreateThreadOne().start();
new CreateThreadTwo();
  • 线程的生命周期

    新建状态(new-创建对象即进入新建状态)
    就绪状态(runnable,调用.start()方法即进入就绪状态)
    运行状态(running此时线程真正执行)
    阻塞状态(Blocked)
    死亡状态(线程执行完毕或者是异常退出,该线程结束生命周期。)

阻塞状态分类
等待阻塞:运行状态中的线程执行wait()方法,使本线程进入到等待阻塞状态;
同步阻塞:线程在获取synchronized同步锁失败(因为锁被其它线程占用),它会进入到同步阻塞状态;
其他阻塞:通过调用线程的sleep()或join()或发出I/O请求时,线程会进入到阻塞状态。当sleep()状态超时、join()等待线程终止或者超时、或者I/O处理完毕时,线程重新转入就绪状态。

线程同步的有几种方法  详细介绍传送门:
https://blog.csdn.net/scgyus/article/details/79499650

1、使用synchronized关键字
2、wait和notify
3、使用特殊域变量volatile实现线程同步
4、使用重入锁实现线程同步
5、使用局部变量来实现线程同步
6、使用阻塞队列实现线程同步
7、使用原子变量实现线程同步

  • java中多线程通信方式

    在java中多线程间的通信使用的是等待/通知机制来实现的
    android中线程间通信:Handle(2种创建方式:主线程、子线程)、接口、广播等

    synchronied关键字等待/通知机制:是指一个线程A调用了对象O的wait()方法进入等待状态,而另一个线程B调用了对象O的notify()或者notifyAll()方法,线程A收到通知后从对象O的wait()方法返回,进而执行后续操作。上述的两个线程通过对象O来完成交互,而对象上的wait()和notify()/notifyAll()的关系就如同开关信号一样,用来完成等待方和通知方之间的交互工作。

    等待/通知机制主要是用到的函数方法是notify()/notifyAll(),wait()/wait(long),wait(long,int),这些方法在上一篇文章都有说明过,这里就不重复了。当然这是针对synchronied关键字修饰的函数或代码块,因为要使用notify()/notifyAll(),wait()/wait(long),wait(long,int)这些方法的前提是对调用对象加锁,也就是说只能在同步函数或者同步代码块中使用。

    条件对象的等待/通知机制:所谓的条件对象也就是配合前面我们分析的Lock锁对象,通过锁对象的条件对象来实现等待/通知机制。那么条件对象是怎么创建的呢?

Condition conditionObj=ticketLock.newCondition();//创建


  • 线程共享的区域有哪些

    由所有线程共享的数据区是:方法区和堆

  • 线程死锁的原因?来源-那个人
    https://juejin.im/post/59e9ac446fb9a045167c520a

    死锁是这样一种情形:多个线程同时被阻塞,它们中的一个或者全部都在等待某个资源被释放.由于线程被无限期地阻塞,因此程序不能正常运行。

    导致死锁的根源在于不适当地运用“synchronized”关键词来管理线程对特定对象的访问.“synchronized”关键词的作用是,确保在某个时刻只有一个线程被允许执行特定的代码块,因此,被允许执行的线程首先必须拥有对变量或对象的排他性访问权.当线程访问对象时,线程会给对象加锁,而这个锁导致其它也想访问同一对象的线程被阻塞,直至第一个线程释放它加在对象上的锁

  • 出现死锁可能的原因

当我们了解在什么情况下会产生死锁,以及什么是死锁的时候,我们在写代码的时候应该尽量的去避免这个误区.产生死锁必须同时满足以下四个条件,只要其中任一条件不成立,死锁就不会发生.
1、 互斥条件:线程要求对所分配的资源进行排他性控制,即在一段时间内某 资源仅为一个进程所占有.此时若有其他进程请求该资源.则请求进程只能等待.
2、不剥夺条件:进程所获得的资源在未使用完毕之前,不能被其他进程强行夺走,即只能由获得该资源的线程自己来释放(只能是主动释放).
3、请求和保持条件:线程已经保持了至少一个资源,但又提出了新的资源请求,而该资源已被其他线程占有,此时请求线程被阻塞,但对自己已获得的资源保持不放.
4、循环等待条件:存在一种线程资源的循环等待链,链中每一个线程已获得的资源同时被链中下一个线程所请求。

  • 避免死锁的方法

1.加锁顺序

http://ifeve.com/deadlock-prevention/#ordering

2.加锁时限

http://ifeve.com/deadlock-prevention/#timeout

3.死锁检测

http://ifeve.com/deadlock-prevention/#detection

参考资料

http://www.cnblogs.com/vinozly/p/5240204.html

  • 对java中虚拟机(jvm)的理解 资料

https://www.diycode.cc/topics/597

内存管理机制

进程

  • java中的多进程

  • 线程与进程的区别

    线程是进程的组成部分,一个进程可以有很多线程,每条线程并行执行不同的任务。
    不同的进程使用不同的内存空间,而线程与父进程的其他线程共享父进程的所拥有的全部资源。这样编程方便了,但是要更加小心。
    每个线程都拥有单独的栈内存用来存储本地数据。线程拥有自己的堆栈、自己的程序计数器和自己的局部变量,但不拥有系统资源。别把内存空间和栈内存搞混

    线程的调度和管理由进程本身负责完成。操作系统对进程进行调度,管理和资源分配。

  • 多线程优势

    进程之间不能共享内存,但线程之间共享内存。
    系统创建进程时需要为该进程重新分配系统资源,但创建线程则代价小很多,效率高。
    资源利用率更好
    程序设计更简单
    程序响应更快

  • 进程间通讯方式

(1)管道(Pipe):管道可用于具有亲缘关系进程间的通信,允许一个进程和另一个与它有共同祖先的进程之间进行通信。
(2)命名管道(named pipe):命名管道克服了管道没有名字的限制,除具有管道所具有的功能外,它还允许无亲缘关系进程间的通信。
(3)信号(Signal):信号是比较复杂的通信方式,用于通知接受进程有某种事件发生,除了用于进程间通信外,进程还可以发送 信号给进程本身。
(4)消息(Message)队列:消息队列是消息的链接表,包括Posix消息队列system V消息队列。
(5)共享内存:使得多个进程可以访问同一块内存空间,是最快的可用IPC形式。是针对其他通信机制运行效率较低而设计的。
(6)内存映射(mapped memory):内存映射允许任何多个进程间通信,每一个使用该机制的进程通过把一个共享的文件映射到自己的进程地址空间来实现它。
(7)信号量(semaphore):主要作为进程间以及同一进程不同线程之间的同步手段。
(8)套接口(Socket):更为一般的进程间通信机制,可用于不同机器之间的进程间通信。
java中GC回收机制

  • HashMap与HashTable的区别

    hashMap线程不安全,hashtable线程安全

    hashMap允许key=null,value=null;hashTable不允许

    hashTable的方法是被synchronized的,hashMap不是,多线程同时操作hashMap时会出现问题,需要设置实现同步方法

    HashTable 继承自 Dictionary 类,而 HashMap 是 Java1.2 引进的 Map interface 的一个实现

Hashtable<K,V> extends Dictionary<K,V> implements Map<K,V>, Cloneable, java.io.Serializable
HashMap<K,V> extends AbstractMap<K,V> implements Map<K,V>, Cloneable, Serializable

abstract class AbstractMapimplements Map,v>

了解更多一点Map

https://blog.csdn.net/qq_30683329/article/details/80455779

  • HashMap的底层实现

  • I/O操作为什么要用缓冲流

    目的:提高处理(复制)文件的效率

    字节缓冲流:BufferedInputStream,BufferedOutputStream

    字符缓冲流:BufferedReader,BufferedWriter
    缓冲流类属于处理流,因此必须结合节点流来使用

字节缓冲流类结合 : FileInputStream, FileOutputStream
  字符缓冲流类结合:FileReader,FileWriter

  • String StringBuffer与StringBuilder的区别

     String是不可变字符串通过“+”看上去字符串变了,实际上在内存中生成了   多个字符串对象
     StringBuffer与StringBuilder都是可变字符串.append("追加的字符")
     StringBuffer线程安全,效率较低
     StringBuilder线程不安全,效率较高

  • 用过哪些集合,都有什么特点,底层实现

     ArrayList元素在位置上有序,可以重复,插入或删除元素较慢,查找效率    高,采用队列来管理元素
    LinkedList元素在位置上有序,可以重复,插入或删除元素较快,查找效率较 低,采用链表原理管理所有元素

  • Context的子类

      Android中Context的子类
      context是一个抽象类(public abstract class Context {})
      这篇介绍Context的文章很详细类

https://blog.csdn.net/guolin_blog/article/details/47028975

  • java中内存泄漏

  • java的性能优化

  • 注解

  • 反射

  • 范型

设计模式

三个分类 摘自博客

https://www.cnblogs.com/pony1223/p/7608955.html

  • 创建型模式:对象实例化的模式,创建型模式用于解耦对象的实例化过程。

  • 结构型模式:把类或对象结合在一起形成一个更大的结构。

  • 行为型模式:类和对象如何交互,及划分责任和算法

image.png

02 网络编程



  • TCP/IP协议四层模型

  • tcp与udp

  • http

  • https

  • http与http区别

03 算法


  • 冒泡排序

    思想:从第一个元素开始进行两两比较,根据大小交换位置,直到最后将最大(小)的数据元素交换到了无序队列的队尾,从而成为有序序列的一部分;下一次继续这个过程,直到所有数据元素都排好序。

public static void sort(int[] arr) {
        int i, j, temp, len = arr.length;
        for (i = 0; i < len - 1; i++)
            for (j = 0; j < len - 1 - i; j++)
                if (arr[j] > arr[j + 1]) {
                    temp = arr[j];
                    arr[j] = arr[j + 1];
                    arr[j + 1] = temp;
                }
}
  • 单向链表

    一个节点指向另一个节点

//实体类-每个节点封装
public class Node {

    //数据域
    public int data;

    //指针域,指向下一个节点
    public Node next;

    public Node() {
    }

    public Node(int data) {
        this.data = data;
    }

    public Node(int data, Node next) {
        this.data = data;
        this.next = next;
    }
}
04 Android篇


四大组件

  • activity
    要知道四种启动模式都是什么,有什么区别,各个生命周期方法,主题修改等

  • service
    如何使用,2种不同启动方式,有什么不同,生命周期,运行在那个线程

  • ContentProvider
    如何使用

  • BroadcastReceiver
    使用方法,2种注册(AndroidManifest.xml种静态注册、动态注册)方式及区别

  • IntentService

  • Fragment

  • application的生命周期

  • Service生命周期及用法

  • support包下有哪些新控件

  • 自定义View

  • Touch事件分发

  • View的渲染过程

  • android开机启动流程

  • 进程保活

  • IPC

  • ThreadLocal原理

  • Handler的创建方式

    1、在主线程(UI线程)创建

public class ThreadDemo extends AppCompatActivity {
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initData();
    }

    MyHandler handler = new MyHandler();

    private static class MyHandler extends Handler {
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            //接收消息处理
            //do something
        }
    }

    private void initData() {
        new Thread(new Runnable() {
            @Override
            public void run() {
                SystemClock.sleep(1000);
                //发送消息
                handler.sendEmptyMessage(0);

            }
        }).start();
    }
}

2、在子线程中创建

  new Thread(new Runnable() {
            @Override
            public void run() {
                Looper.prepare();
                Handler myHandler = new Handler(){
                    @Override
                    public void handleMessage(Message msg) {
                        super.handleMessage(msg);

                    }
                };
                myHandler.sendEmptyMessage(1);
                Looper.loop();

            }
        }).start();
  • Handler机制

  • AIDL

  • 对播放器的了解

  • Service运行在什么线程
    service运行在UI(主)线程

  • Android原生与h5如何交互

  • FramWork的工作方式和原理?Activity是如何生成一个view的?

05 架构模式



  • mvp mvc mvvm

  • JNI流程

  • 指针作用,占多少内存

  • 二级指针作用,占多少内存

  • 如何生成so库文件

  • 如何选用三方框架

  • Lambda 表达式
    lambada表达式的java8的新特性,lambda表达式允许你通过表达式来代替功能接口。 lambda表达式就和方法一样,它提供了一个正常的参数列表和一个使用这些参数的主体(body,可以是一个表达式或一个代码块)

基本语法:

(parameters) -> expression 或 (parameters) ->{ statements; }

appName.setOnClickListener(v -> {//TODO do something });
appName.setOnClickListener(v -> Toast.makeText(this, "这是一个吐司", Toast.LENGTH_SHORT).show());
  • adb的使用,如何查看cpu内存情况

  • 无线连接手机的原理

  • 安全性怎么保证

  • 如何保证一个app的稳定性

06 Android面试之性能优化



  • 启动优化

  • 代码优化

  • 内存优化

  • 电量优化

  • 布局优化

  • 网络优化

07 版本控制-Git



  • git相关命令

  • git:如何解决冲突,命令行指令(手写)

08 UML类图



  • 依赖关系(dependence)

  • 泛化关系

  • 关联关系

  • 聚合关系

  • 组合关系

  • 实现关系(implementation)

09 面试之HR and 对话


  • 自我介绍

  • 项目介绍
    挑一个熟悉的,参与时间较长的来详细介绍一下,其他的简单介绍下或者看面试官需不需要了解再决定

  • 在开发过程中遇到的最大困难是什么?怎么解决的?

  • 离职原因

  • 说说自己的优缺点

  • 问面试者对公司有什么想问的?

(仅供参考)
1、公司目前的业务是做什么的?(大体了解)
2、公司目前的项目面临的最大困难是什么?(如果面试成功,这很有可能是你要面对的了;还有就是很多面试官也会问你同样的问题,哈哈….相信很多人都被问过吧)
3、如果能进入公司,主要工作是做什么?(了解工作内容看是否能够胜任吧)
4、通过这次面试,您觉得我还有哪些不足?能给点建议和指导吗?(成长)
5、对于离职率大的公司,问:您觉得离职率这么大的主要原因是什么呢?(更一步了解)

10 大话职业规划


  • 说说你未来的职业规划(5年、10年)

    1、专精技术路线(工程师->初级工程师->中级工程师->高级工程师->资深工程师->技术专家->行业科学家)

    2、技术与某一具体行业结合 深入耕耘成为某一行业的顶尖技术人才

    3、先做技术,在合适的时机(机遇到来时)转向管理岗

    4、积累一笔资金去创业

    其他

11 源码



  • 第三方框架源码的研究

12 总结


由于个人掌握知识的水平有限,如有表达有误或不够完善的,欢迎大家评论指出
内容很多,工作很忙,所以正在逐步完善中,欢迎大家一起来共同完善~

如果您觉得不错,请别忘了转发、分享、点赞让更多的人去学习, 您的举手之劳,就是对小乐最好的支持,非常感谢!

如何您想进技术群交流,关注公众号在后台回复 “加群”,或者 “学习” 即可

著作权归作者所有,欢迎大家投稿


推荐阅读

阿里、腾讯、百度、华为、京东最新面试题汇集

宇宙最全的架构开发技术百科全书
初入职场,这几条你做到了么?
软件测试工程师的岗位职责


看完本文有收获?请转发分享给更多人
关注「程序员小乐」,提升技能

    您可能也对以下帖子感兴趣

    文章有问题?点此查看未经处理的缓存